﻿using System;
using System.Collections.Generic;

namespace Bricks.Injecting
{

    /// <summary>
    /// 
    /// </summary>
    public static class ServiceLocator
    {

        /// <summary>
        /// 
        /// </summary>
        private static Func<IContainerFacade> _containerFacadeAccessor;

        /// <summary>
        /// 
        /// </summary>
        public static IContainerFacade Current
        {
            get { return _containerFacadeAccessor.Invoke(); }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="containerFacadeAccessor"></param>
        public static void Initialize(Func<IContainerFacade> containerFacadeAccessor)
        {
            _containerFacadeAccessor = containerFacadeAccessor;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <returns></returns>
        public static object Using(this object instance, Type serviceType)
        {
            return Current.Resolve(serviceType);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object Using(this object instance, Type serviceType, string key)
        {
            return Current.Resolve(serviceType, key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <returns></returns>
        public static IEnumerable<object> UsingAll(this object instance, Type serviceType)
        {
            return Current.ResolveAll(serviceType);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static TService Using<TService>(this object instance)
        {
            return Current.Resolve<TService>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static TService Using<TService>(this object instance, string key)
        {
            return Current.Resolve<TService>(key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static IEnumerable<TService> UsingAll<TService>(this object instance)
        {
            return Current.ResolveAll<TService>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public static bool TryUsing(this object instance, Type serviceType, out object service)
        {
            return Current.TryResolve(serviceType, out service);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <param name="key"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public static bool TryUsing(this object instance, Type serviceType, string key, out object service)
        {
            return Current.TryResolve(serviceType, key, out service);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="serviceType"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public static bool TryUsingAll(this object instance, Type serviceType, out IEnumerable<object> services)
        {
            return Current.TryResolveAll(serviceType, out services);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public static bool TryUsing<TService>(this object instance, out TService service)
        {
            return Current.TryResolve<TService>(out service);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <param name="key"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public static bool TryUsing<TService>(this object instance, string key, out TService service)
        {
            return Current.TryResolve<TService>(key, out service);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="instance"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public static bool TryUsingAll<TService>(this object instance, out IEnumerable<TService> services)
        {
            return Current.TryResolveAll<TService>(out services);
        }
    }
}
